/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.stream.commontools.concurrent.resourcepool.limited;

import cn.ac.iie.stream.commontools.concurrent.Closable;
import cn.ac.iie.stream.commontools.concurrent.resourcepool.ResourcePool;
import java.util.HashSet;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
 * @author zwlin
 */
public abstract class ClosableLimitedResourcePool<Resource extends Closable> implements ResourcePool<Resource>, Closable {

	boolean closeSignal;
	final ReentrantReadWriteLock signalLock;

	final HashSet<Resource> identificationSet;

	final LinkedBlockingQueue<Resource> resourceQueue;

	public ClosableLimitedResourcePool(int capacity) {
		closeSignal = false;
		signalLock = new ReentrantReadWriteLock();
		identificationSet = new HashSet<Resource>(capacity);
		resourceQueue = new LinkedBlockingQueue<Resource>(capacity);
		for (int i = 0; i < capacity; ++i) {
			Resource r = GetNewResource();
			identificationSet.add(r);
			resourceQueue.add(r);
		}
	}

	@Override
	public Resource BorrowResource() {
		signalLock.readLock().lock();
		try {
			if (closeSignal) {
				return null;
			} else {
			}
		} finally {
			signalLock.readLock().unlock();
		}
		try {
			return resourceQueue.take();
		} catch (InterruptedException ex) {
			return null;
		}
	}

	@Override
	public boolean ReturnResource(Resource resource) {
		//验证resource是否属于此pool
		if (identificationSet.contains(resource)) {
		} else {
			return false;
		}
		try {
			//归还
			resourceQueue.put(resource);
		} catch (InterruptedException ex) {
			throw new Error(ex);
		}
		return true;
	}

	@Override
	public void CloseGracefully() {
		//更改信号量
		signalLock.writeLock().lock();
		try {
			closeSignal = true;
		} finally {
			signalLock.writeLock().unlock();
		}
		//关闭
		for (Resource r : identificationSet) {
			r.CloseGracefully();
		}
	}

	@Override
	public void ForceClose() {
		//更改信号量
		signalLock.writeLock().lock();
		try {
			closeSignal = true;
		} finally {
			signalLock.writeLock().unlock();
		}
		//关闭
		for (Resource r : identificationSet) {
			r.ForceClose();
		}
	}

	@Override
	abstract public Resource GetNewResource();

}
